#include "../KmyMath.h"

#include "KmySprite.h"
#include "../KmyICanvas.h"
#include "../KmyResourceManager.h"

KmySprite::KmySprite()
{
    parent = NULL;
    sprite_template = NULL;
    alpha = 1.0;
}

KmySprite::KmySprite(KmySpriteTemplate *st){
    parent = NULL;
    sprite_template = st;
    visible = true;
    is_updated=false;
    alpha = 1.0;

    int x1 = sprite_template->max_range.x;
    int y1 = sprite_template->max_range.y;
    int x2 = sprite_template->max_range.x+sprite_template->max_range.w;
    int y2 = sprite_template->max_range.y+sprite_template->max_range.h;
    max_range.x = MIN(x1, -x2);
    max_range.y = MIN(y1, -y2);
    max_range.w = -max_range.x*2;
    max_range.h = -max_range.y*2;
}

KmySprite::~KmySprite(){

}

void KmySprite::initialize(){
    cur_anime_index = 0;
    cur_frame_index = 0;
    animation_state = KmySprite::ANIMATION_STATE_STOP;
    speed_x = 0;
    speed_y = 0;
    flip = 0;
    angle = 0;
    z = 0;
    x = 0;
    y = 0;
}

void KmySprite::finalize(){
    sprite_template = NULL;
}

void KmySprite::getActiveRange(St_Rect &range){
    range.x = x+max_range.x;
    range.y = y+max_range.y;
    range.w = max_range.w;
    range.h = max_range.h;
}

void KmySprite::setAnime(int index){
    if (sprite_template->anime_num<=index){
        return;
    }
    cur_anime_index = index;
    cur_frame_index = 0;
    is_updated = true;
}

void KmySprite::setAnimeByName(string &aname){
    if (aname == sprite_template->animes[cur_anime_index].name){
        return;
    }
    for (int i=0; i<sprite_template->anime_num; i++){
        if (sprite_template->animes[i].name == aname){
            cur_anime_index = i;
            cur_frame_index = 0;
            is_updated = true;
            return;
        }
    }
}

void KmySprite::setFrame(int index){
    if (sprite_template->animes[cur_anime_index].frame_num<=index){
        return;
    }
    cur_frame_index = index;
    is_updated = true;
}

bool KmySprite::nextFrame(){
    if (cur_frame_index<sprite_template->animes[cur_anime_index].frame_num-1){
        cur_frame_index++;
        is_updated = true;
        return true;
    }else{
        return false;
    }
}

void KmySprite::nextCycFrame(){
    cur_frame_index = (cur_frame_index+1)%sprite_template->animes[cur_anime_index].frame_num;
    is_updated = true;
}

void KmySprite::setPosition(int x, int y, int z){
    this->x = x;
    this->y = y;
    this->z = z;
    is_updated = true;
}

int KmySprite::getNodeType(){
    return KmyNode::NODE_TYPE_SPRITE;
}

void KmySprite::logic(){
    if (speed_x!=0 || speed_y!=0){
        x += speed_x;
        y += speed_y;
        is_updated = true;
    }
    switch(animation_state){
    case ANIMATION_STATE_STOP:
        break;
    case ANIMATION_STATE_PLAY:
        nextFrame();
        break;
    case ANIMATION_STATE_LOOP:
        nextCycFrame();
        break;
    }
}

void KmySprite::render(KmyICanvas *screen){
    if (visible==false){
        return;
    }
    if (sprite_template->imagepak==NULL){
        KmyResourceManager *krm = KmyResourceManager::getInstance();
        sprite_template->imagepak = krm->getImage(sprite_template->imagepakname);
    }

    if (drawtask==NULL || is_updated){
        ST_anime *cur_anime = &sprite_template->animes[cur_anime_index];
        int frame_index = cur_anime->image_frame_indexs[cur_frame_index];
        ST_indexs *cur_frame = &sprite_template->ifs[frame_index];

        int gx = getGlobalX();
        int gy = getGlobalY();

    //    for (int i = 0; i<cur_frame->num; i++){
    //        int part_index = cur_frame->indexs[i];
    //        ST_imagePart *part = &sprite_template->image_parts[part_index];
    //        screen->addDrawTaskImageS(sprite_template->imagepak,
    //                            part->image_index,
    //                            x+part->x,
    //                            y+part->y,
    //                            z+i
    //                            //  alpha, angle, flip
    //                            );
    //    }
        int frag_num = cur_frame->num;
        St_Rect* srects = new St_Rect[frag_num];
        St_Rect2* drects = new St_Rect2[frag_num];
        switch (flip){
        case 0:
            for (int i = 0; i<frag_num; i++){
                int part_index = cur_frame->indexs[frag_num-i-1];
                ST_imagePart *part = &sprite_template->image_parts[part_index];
                St_Rect *range = &(sprite_template->imagepak->ranges[part->image_index]);
                srects[i].x = range->x;
                srects[i].y = range->y;
                srects[i].w = range->w;
                srects[i].h = range->h;
                drects[i].x = gx+part->x;
                drects[i].y = gy+part->y;
                drects[i].w = range->w;
                drects[i].h = range->h;
                drects[i].flip = flip;
            }
            break;
        case 1: // x翻转
            for (int i = 0; i<frag_num; i++){
                int part_index = cur_frame->indexs[frag_num-i-1];
                ST_imagePart *part = &sprite_template->image_parts[part_index];
                St_Rect *range = &(sprite_template->imagepak->ranges[part->image_index]);
                srects[i].x = range->x;
                srects[i].y = range->y;
                srects[i].w = range->w;
                srects[i].h = range->h;
                drects[i].x = gx - part->x - range->w;
                drects[i].y = gy + part->y;
                drects[i].w = range->w;
                drects[i].h = range->h;
                drects[i].flip = flip;
            }
            break;
        case 2: // y翻转
            for (int i = 0; i<frag_num; i++){
                int part_index = cur_frame->indexs[frag_num-i-1];
                ST_imagePart *part = &sprite_template->image_parts[part_index];
                St_Rect *range = &(sprite_template->imagepak->ranges[part->image_index]);
                srects[i].x = range->x;
                srects[i].y = range->y;
                srects[i].w = range->w;
                srects[i].h = range->h;
                drects[i].x = gx + part->x;
                drects[i].y = gy - part->y - range->h;
                drects[i].w = range->w;
                drects[i].h = range->h;
                drects[i].flip = flip;
            }
            break;
        case 3: // xy翻转
            for (int i = 0; i<frag_num; i++){
                int part_index = cur_frame->indexs[frag_num-i-1];
                ST_imagePart *part = &sprite_template->image_parts[part_index];
                St_Rect *range = &(sprite_template->imagepak->ranges[part->image_index]);
                srects[i].x = range->x;
                srects[i].y = range->y;
                srects[i].w = range->w;
                srects[i].h = range->h;
                drects[i].x = gx - part->x - range->w;
                drects[i].y = gy - part->y - range->h;
                drects[i].w = range->w;
                drects[i].h = range->h;
                drects[i].flip = flip;
            }
            break;
        }
        if (drawtask==NULL){
            drawtask = screen->addDrawTaskMultiImage(sprite_template->imagepak->image,
                                          frag_num, srects, drects,
                                          z, 1.0f, angle);
        }else{
            drawtask->updatePlural(frag_num, srects, drects,z, 1.0f, angle);
            is_updated = false;
            screen->addDrawTask(drawtask);
        }
        delete[] srects;
        delete[] drects;
    }else{
        screen->addDrawTask(drawtask);
    }

    KmyNode::render(screen);
}

//void KmySprite::render(KmyICanvas *screen, St_Rect *camera){
//    if (visible==false){
//        return;
//    }
//    if (isInCamera(camera)){
//        if (sprite_template->imagepak==NULL){
//            KmyResourceManager *krm = KmyResourceManager::getInstance();
//            sprite_template->imagepak = krm->getImage(sprite_template->imagepakname);
//        }
//        ST_anime *cur_anime = &sprite_template->animes[cur_anime_index];
//        int frame_index = cur_anime->image_frame_indexs[cur_frame_index];
//        ST_indexs *cur_frame = &sprite_template->ifs[frame_index];
////        for (int i = 0; i<cur_frame->num; i++){
////            ST_imagePart *part = &sprite_template->image_parts[cur_frame->indexs[i]];
////            screen->addDrawTaskImageS(sprite_template->imagepak,
////                                part->image_index,
////                                x-camera->x+part->x,
////                                y-camera->y+part->y,
////                                z+i
////                                //  alpha, angle, flip
////                                );
////        }

//        int frag_num = cur_frame->num;
//        St_Rect* srects = new St_Rect[frag_num];
//        St_Rect2* drects = new St_Rect2[frag_num];
//        switch (flip){
//        case 0:
//            for (int i = 0; i<frag_num; i++){
//                int part_index = cur_frame->indexs[frag_num-i-1];
//                ST_imagePart *part = &sprite_template->image_parts[part_index];
//                St_Rect *range = &(sprite_template->imagepak->ranges[part->image_index]);
//                srects[i].x = range->x;
//                srects[i].y = range->y;
//                srects[i].w = range->w;
//                srects[i].h = range->h;
//                drects[i].x = x+part->x-camera->x;
//                drects[i].y = y+part->y-camera->y;
//                drects[i].w = range->w;
//                drects[i].h = range->h;
//                drects[i].flip = flip;
//            }
//            break;
//        case 1: // x翻转
//            for (int i = 0; i<frag_num; i++){
//                int part_index = cur_frame->indexs[frag_num-i-1];
//                ST_imagePart *part = &sprite_template->image_parts[part_index];
//                St_Rect *range = &(sprite_template->imagepak->ranges[part->image_index]);
//                srects[i].x = range->x;
//                srects[i].y = range->y;
//                srects[i].w = range->w;
//                srects[i].h = range->h;
//                drects[i].x = x - part->x - range->w -camera->x;
//                drects[i].y = y + part->y -camera->y;
//                drects[i].w = range->w;
//                drects[i].h = range->h;
//                drects[i].flip = flip;
//            }
//            break;
//        case 2: // y翻转
//            for (int i = 0; i<frag_num; i++){
//                int part_index = cur_frame->indexs[frag_num-i-1];
//                ST_imagePart *part = &sprite_template->image_parts[part_index];
//                St_Rect *range = &(sprite_template->imagepak->ranges[part->image_index]);
//                srects[i].x = range->x;
//                srects[i].y = range->y;
//                srects[i].w = range->w;
//                srects[i].h = range->h;
//                drects[i].x = x + part->x -camera->x;
//                drects[i].y = y - part->y - range->h -camera->y;
//                drects[i].w = range->w;
//                drects[i].h = range->h;
//                drects[i].flip = flip;
//            }
//            break;
//        case 3: // xy翻转
//            for (int i = 0; i<frag_num; i++){
//                int part_index = cur_frame->indexs[frag_num-i-1];
//                ST_imagePart *part = &sprite_template->image_parts[part_index];
//                St_Rect *range = &(sprite_template->imagepak->ranges[part->image_index]);
//                srects[i].x = range->x;
//                srects[i].y = range->y;
//                srects[i].w = range->w;
//                srects[i].h = range->h;
//                drects[i].x = x - part->x - range->w -camera->x;
//                drects[i].y = y - part->y - range->h -camera->y;
//                drects[i].w = range->w;
//                drects[i].h = range->h;
//                drects[i].flip = flip;
//            }
//            break;
//        }
//        screen->addDrawTaskMultiImage(sprite_template->imagepak->image,
//                                      frag_num, srects, drects,
//                                      z, 1.0f, angle);
//        delete srects;
//        delete drects;
//    }

//    KmyNode::render(screen);
//}

bool KmySprite::isInCamera(St_Rect *camera){
    St_Rect spt_range;
    getActiveRange(spt_range);
    if (spt_range.x+spt_range.w<camera->x
            || spt_range.x>camera->x+camera->w
            || spt_range.y+spt_range.h<camera->y
            || spt_range.y>camera->y+camera->h){
        return false;
    }
    return true;
}

bool KmySprite::isInScreen(KmyICanvas* screen){
    int gx = getGlobalX();
    int gy = getGlobalY();
    if (gx+max_range.x+max_range.w<0
            ||gx+max_range.x>screen->WIDTH
            ||gy+max_range.y+max_range.h<0
            ||gy+max_range.y>screen->HEIGHT){
        return false;
    }
    return true;
}

int KmySprite::getFlip(){
    return flip;
}

float KmySprite::getAngle(){
    return angle;
}

float KmySprite::getAlpha(){
    return alpha;
}

void KmySprite::setFlip(int flip){
    if (this->flip!=flip){
        is_updated = true;
        this->flip = flip;
    }
}

void KmySprite::setAngle(float a){
    if (this->angle!=a){
        this->angle = a;
        if (drawtask!=NULL){
            drawtask->updateAngle(this->angle);
        }
    }
}

void KmySprite::setAlpha(float a){
    if (this->alpha!=a){
        this->alpha = a;
        if (drawtask!=NULL){
            drawtask->updateAlpha(this->alpha);
        }
    }
}
